package service

import (
	"context"
	"errors"
	"fmt"
	"go.uber.org/zap"
	"math/rand"
	"seichat/biz"
	"seichat/common"
	"seichat/dao"
	"seichat/middlerware"
	"seichat/models"
	"time"
)

type UserService interface {
	GetUserList(ctx context.Context) ([]*models.User, error)
	FindUserByName(ctx context.Context, name string) (*models.User, error)
	LoginByNameAndPassWord(ctx context.Context, name, password string) (*models.User, string, error)
	NewUser(ctx context.Context, name, password, repassword string) (*models.User, error)
	UpdateUser(ctx context.Context, user models.User) (*models.User, error)
	DeleteUser(ctx context.Context, user models.User) error
	FindUserById(ctx context.Context, id uint) (*models.User, error)
	SendMessage(ctx context.Context, key string, start int64, end int64, isRev bool) ([]string, error)
}
type UserServiceImpl struct {
	dao     dao.UserDao
	message dao.MessageDao
}

func NewUserService(dao dao.UserDao, message dao.MessageDao) UserService {
	return &UserServiceImpl{
		dao:     dao,
		message: message,
	}
}
func (s *UserServiceImpl) FindUserById(ctx context.Context, id uint) (*models.User, error) {
	user, err := s.dao.FindUserId(ctx, id)
	if err != nil {
		return &models.User{}, err
	}
	return user, nil
}

func (s *UserServiceImpl) DeleteUser(ctx context.Context, user models.User) error {
	err := s.dao.DeleteUser(ctx, user)
	if err != nil {
		return errors.New("注销用户失败")
	}
	return nil
}

func (s *UserServiceImpl) NewUser(ctx context.Context, name, password, repassword string) (*models.User, error) {
	//查询用户是否存在
	if _, err := s.dao.FindUserByName(ctx, name); errors.Is(biz.AlreadyRegister, err) {
		return nil, biz.AlreadyRegister
	}
	if password != repassword {
		return nil, errors.New("两次输入的密码不一致")
	}
	//生成盐值
	salt := fmt.Sprintf("%d", rand.Int31())
	//加密密码
	var user models.User
	user.Name = name
	user.PassWord = common.SaltPassWord(password, salt)
	user.Salt = salt
	t := time.Now()
	user.LoginTime = &t
	user.LoginOutTime = &t
	user.HeartBeatTime = &t
	createUser, err := s.dao.CreateUser(ctx, user)
	if err != nil {
		return nil, err
	}
	return createUser, nil
}

func (s *UserServiceImpl) GetUserList(ctx context.Context) ([]*models.User, error) {
	list, err := s.dao.GetUserList(ctx)
	if err != nil {
		return nil, err
	}
	return list, nil
}

func (s *UserServiceImpl) FindUserByName(ctx context.Context, name string) (*models.User, error) {
	user, err := s.dao.FindUserByName(ctx, name)
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (s *UserServiceImpl) LoginByNameAndPassWord(ctx context.Context, name, password string) (*models.User, string, error) {
	data, err := s.dao.FindUserByNameAndPwd(ctx, name, password)
	if err != nil {
		return nil, "", errors.New("登录失败")
	}
	//用户名不存在
	if data.Name == "" {
		return nil, "", errors.New("用户名不存在")
	}
	//使用了md5加密， 所以验证密码时，是将密码再次加密，然后进行对比
	ok := common.CheckPassWord(password, data.Salt, data.PassWord)
	if !ok {
		return nil, "", errors.New("密码错误")
	}
	rsp, err := s.dao.FindUserByNameAndPwd(ctx, name, data.PassWord)
	if err != nil {
		zap.S().Info("登录失败", err)
		return nil, "", errors.New("登录失败")
	}
	//这里使用jwt做权限认证
	token, err := middlerware.GenerateToken(rsp.ID, "yk")
	if err != nil {
		zap.S().Info("生成token失败", err)
		return nil, "", biz.TokenError
	}
	return rsp, token, nil
}
func (s *UserServiceImpl) UpdateUser(ctx context.Context, user models.User) (*models.User, error) {
	rsp, err := s.dao.UpdateUser(ctx, user)
	if err != nil {
		zap.S().Info("更新用户失败", err)
		return nil, errors.New("修改信息失败")
	}
	return rsp, nil
}
func (s *UserServiceImpl) SendMessage(ctx context.Context, key string, start int64, end int64, isRev bool) ([]string, error) {
	list, err := s.message.RedisMsg(ctx, key, start, end, isRev)
	if err != nil {
		zap.S().Info("发送消息失败", err)
		return nil, errors.New("发送消息失败")
	}
	return list, nil
}
